﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using FrameWork.Source.Animation_Classes;
using FrameWork.Source.Resource_Manager;
using FrameWork.Source.Texture;
using Boomer.Source.TiledMap;
using Microsoft.Xna.Framework.Input;
using Boomer.Source.Boom;
using Microsoft.Xna.Framework;
using FrameWork.Source.Global_variables;

namespace Boomer.Source.Character
{
    class CPlayer : CCharacter
    {
        public enum PlayerState
        {
            Stand = 0 ,
            StandAnim = 1 ,
            MoveLeft = 2 ,
            MoveRight = 3 ,
            MoveTop = 4 ,
            MoveBot = 5
        }

        private PlayerState currState;

        private float timePlayAnim;
        private bool isPlayingAnim;
        private float timeDelay;

        private bool isReleaseSpace;
        private bool isReleaseX;

        private bool isIllusion;
        private bool isHasIllusion;

        private CPlayer illusion;

        private float dieTime;
        private float maxDieTime;

        public CPlayer()
            : base()
        {
            this.Tag = FrameWork.Tag_Manager.TagManager.TAGGED.Player;
            timePlayAnim = 0;
            isPlayingAnim = false;
            isReleaseSpace = false;
            isReleaseX = false;
            isIllusion = false;
            isHasIllusion = false;

            isPress = false;
            isReleaseIlluKey = true;

            dieTime = 0.0f;
            maxDieTime = 2.0f;
            this.speed = 150.0f;
        }
        
        public override void init()
        {
            CAnimation[] pAnim;
            pAnim = new CAnimation[7];

            pAnim[0] = new CAnimation();
            pAnim[0].createAnimation((ulong)PlayerState.Stand, 0, 0, 0, 1.0f);
            pAnim[1] = new CAnimation();
            pAnim[1].createAnimation((ulong)PlayerState.StandAnim, 1, 2, 1, 1.0f / 4.0f);
            pAnim[2] = new CAnimation();
            pAnim[2].createAnimation((ulong)PlayerState.MoveLeft, 3, 7, 3, 1.0f / 10.0f);
            pAnim[3] = new CAnimation();
            pAnim[3].createAnimation((ulong)PlayerState.MoveRight, 8, 12, 8, 1.0f / 10.0f);
            pAnim[4] = new CAnimation();
            pAnim[4].createAnimation((ulong)PlayerState.MoveTop, 13, 17, 13, 1.0f / 10.0f);
            pAnim[5] = new CAnimation();
            pAnim[5].createAnimation((ulong)PlayerState.MoveBot, 18, 22, 18, 1.0f / 10.0f);
            pAnim[6] = new CAnimation();
            pAnim[6].createAnimation("Die", 23, 24, 24, 1.0f / 10.0f);

            CTexture image = CResourceManager.getInstance().getImage((int)CResourceManager.IMG_MAIN.PLAYER);

            loadSprite(image, 23, 10, 66, 82, pAnim);
            createBoundBox(12.0f, 30.0f, 45, 30);
            currState = PlayerState.Stand;
            

            base.init();
        }


        public override void update(float deltaTime)
        {
            if (!isDying)
            {
                processInput(deltaTime);

                if (currState == PlayerState.Stand)
                {
                    timeDelay += deltaTime;
                    if (timeDelay >= 1.0f)
                    {
                        isPlayingAnim = true;
                        timeDelay = 0;
                        changeAnimation((int)PlayerState.StandAnim);
                    }
                }
                else
                {
                    timeDelay = 0;
                }



                if (isHasIllusion)
                    illusion.update(deltaTime);

                if (!isIllusion)
                    CTiledMap.updatePlayerPos(this, this.map);
                if (!isIllusion)
                    base.update(deltaTime);
                else
                    updateAnimation(deltaTime);
            }
            else
            {
                dying(deltaTime);
            }
        }

        private void dying(float deltaTime)
        {
            changeAnimation("Die");
            dieTime += deltaTime;
            if (dieTime >= maxDieTime)
            {
                dieTime = 0.0f;
                m_isAlive = false;
            }
        }

        public override void draw()
        {
            if (isHasIllusion)
                illusion.draw();
            base.draw();
        }

        public override void move(DIRECTION dir, float speed)
        {
            switch (dir)
            {
                case DIRECTION.LEFT :
                    changeAnimation((int)PlayerState.MoveLeft);
                    break;
                case DIRECTION.RIGHT:
                    changeAnimation((int)PlayerState.MoveRight);
                    break;
                case DIRECTION.TOP :
                    changeAnimation((int)PlayerState.MoveTop);
                    break;
                case DIRECTION.BOT :
                    changeAnimation((int)PlayerState.MoveBot);
                    break;
            }

            base.move(dir, speed);
        }

        public override bool Collision(ref global::FrameWork.Source.Object_Classes.CObject pObj)
        {
            return base.Collision(ref pObj);
        }

        private void createIllusion()
        {
            illusion = new CPlayer();
            illusion.init();
            illusion.getSprite().m_fAlpha = 0.7f;
            illusion.m_fDeep = 1.0f;
            illusion.m_isColliable = false;
            illusion.attachMap(this.map);
            illusion.isIllusion = true;
            isHasIllusion = true;
            illusion.m_vec2Position = this.m_vec2Position;
        }

        private void teleport()
        {
            Vector2 pos = map.convertToMapPos(new Vector2(illusion.getBoundBox().X, illusion.getBoundBox().Y));
            Vector2 mapPos = map.convertToMapIndex(pos);
            if (map.getCell((int)mapPos.X, (int)mapPos.Y) != 0)
                return;
            isHasIllusion = false;
            this.m_vec2Position = illusion.m_vec2Position;
        }

        public Vector2 getPos()
        {
            return new Vector2( this.getBoundBox().X , this.getBoundBox().Y );
        }

        public override void processInput(float deltaTime)
        {
            KeyboardState currKeyState = Keyboard.GetState();
            if (!isHasIllusion)
            {
                if (currKeyState.IsKeyDown(Keys.Left))
                {
                    move(DIRECTION.LEFT, -speed * deltaTime);
                    currState = PlayerState.MoveLeft;
                    isPlayingAnim = false;
                    timePlayAnim = 0;
                }
                else if (currKeyState.IsKeyDown(Keys.Right))
                {
                    move(DIRECTION.RIGHT, speed * deltaTime);
                    currState = PlayerState.MoveRight;
                    isPlayingAnim = false;
                    timePlayAnim = 0;
                }
                else if (currKeyState.IsKeyDown(Keys.Up))
                {
                    move(DIRECTION.TOP, -speed * deltaTime);
                    currState = PlayerState.MoveTop;
                    isPlayingAnim = false;
                    timePlayAnim = 0;
                }
                else if (currKeyState.IsKeyDown(Keys.Down))
                {
                    move(DIRECTION.BOT, speed * deltaTime);
                    currState = PlayerState.MoveBot;
                    isPlayingAnim = false;
                    timePlayAnim = 0;
                }
                else
                {
                    if (currState != PlayerState.StandAnim)
                    {
                        if (!isPlayingAnim)
                        {
                            changeAnimation((int)PlayerState.Stand);
                            currState = PlayerState.Stand;
                        }
                    }
                    else
                    {
                        timePlayAnim += deltaTime;
                        if (timePlayAnim >= 2.0f)
                        {
                            isPlayingAnim = false;
                            timePlayAnim = 0;
                        }
                    }
                }

                if (currKeyState.IsKeyDown(Keys.Space))
                {
                    if (this.numBoom > 0 && !isReleaseSpace && !isIllusion)
                    {
                        isReleaseSpace = true;
                        BoomManager.getInstance().createBoom(this, true);
                    }
                }

                if (currKeyState.IsKeyDown(Keys.X))
                {
                    if (this.numActiveBoom > 0 && !isReleaseX && !isIllusion)
                    {
                        isReleaseX = true;
                        BoomManager.getInstance().createBoom(this, false);
                    }
                }
            }

            if (currKeyState.IsKeyDown(Keys.C))
            {
                if( !isIllusion )
                    BoomManager.getInstance().activeBoom();
            }

            if (currKeyState.IsKeyDown(Keys.Z))
            {
                if (isReleaseIlluKey)
                {
                    if( CGLOBAL.g_isPlayingSound)
                        Sound_Manager.SoundManager.getInstance().illusion.Play();
                    isPress = true;
                    isReleaseIlluKey = false;
                    if (!isIllusion && !isHasIllusion)
                    {
                        Effect.CIllusionEffect pEff = new Effect.CIllusionEffect();
                        pEff.init();
                        pEff.createEffect( this.getBoundBox() );
                        Effect.EffectManager.getInstance().addObject(pEff);
                        this.changeAnimation((int)PlayerState.Stand);
                        this.createIllusion();
                    }
                    else if (!isIllusion && isHasIllusion)
                    {
                        Effect.CTeleportEffect pEff = new Effect.CTeleportEffect();
                        pEff.init();
                        pEff.createEffect(this.getBoundBox());
                        Effect.EffectManager.getInstance().addObject(pEff);
                        teleport();
                    }
                }
            }

            if (currKeyState.IsKeyUp(Keys.Space))
            {
                if( isReleaseSpace && !isIllusion )
                    isReleaseSpace = false;
            }
            if (currKeyState.IsKeyUp(Keys.X))
            {
                if (isReleaseX && !isIllusion)
                    isReleaseX = false;
            }

            if (currKeyState.IsKeyUp(Keys.Z))
            {
                if (isPress)
                {
                    isReleaseIlluKey = true;
                    isPress = false;
                }
            }
            base.processInput(deltaTime);
        }

        private bool isReleaseIlluKey;
        private bool isPress;
    }
}
